//
//  MLUserDefault.m
//
//  Created by molon on 3/7/14.
//  Copyright (c) 2014 Molon. All rights reserved.
//

#import "MLUserDefault.h"
#import "MLClassPropManager.h"
#import "Model.h"
#import "ModelArray.h"

NSString * const kPrefixKeyOfUserDefault = @"com.molon.";
@implementation MLUserDefault

+ (instancetype)sharedInstance {
    static MLUserDefault *_sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[[self class] alloc]init];
    });
    return _sharedInstance;
}

- (void)initValues
{
    //这里需要继承做初始化赋值，即为默认值
//    [self doesNotRecognizeSelector:_cmd];
}

- (void)doAfterSetValuesFromUserDefault
{
    //这里在第一次从存储里设置value后，可以选择做的操作
}

- (NSArray *)ignoreKeys
{
    return nil;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        //赋默认值
        [self initValues];
        
        self.disableSynchronize = YES;
        
        //获取属性
        NSDictionary *propToTypes = [[MLClassPropManager manager]propToTypesOfClass:[self class] untilSuperClass:[MLUserDefault class] ignoreUntilClass:YES];
        
        //遍历初始赋值
        NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
        
        NSArray *ignoreKeys = [self ignoreKeys];
        for (NSString *key in [propToTypes allKeys]) {
            if ([ignoreKeys containsObject:key]||[key isEqualToString:@"disableSynchronize"]) {
                continue;
            }
            
            id object = [def objectForKey:[NSString stringWithFormat:@"%@%@",kPrefixKeyOfUserDefault,key]];
            if (object) {
                NSString *type = propToTypes[key];
                if ([type hasPrefix:@"T@\""]&&[type hasSuffix:@"\""]) {
                    type = [type substringWithRange:NSMakeRange(3, [type length]-4)];
                    
                    Class cls = NSClassFromString(type);
                    if ([cls isSubclassOfClass:[Model class]]) {
                        //字典转化成Model
                        if (![object isKindOfClass:[NSDictionary class]]) {
                            DLOG(@"UserDefault里%@并非是字典类型",key);
                            continue;
                        }
                        [self setValue:[cls turnObject:object] forKey:key];
                    }else if ([cls isSubclassOfClass:[ModelArray class]]){
                        //数组转化成ModelArray
                        if (![object isKindOfClass:[NSArray class]]) {
                            DLOG(@"UserDefault里%@并非是数组类型",key);
                            continue;
                        }
                        [self setValue:[cls turnObject:object] forKey:key];
                    }else if ([cls isSubclassOfClass:[NSURL class]]){
                        [self setValue:[NSURL URLWithString:object] forKey:key];
                    }else{
                        [self setValue:object forKey:key];
                    }
                }else{
                    [self setValue:object forKey:key];
                }
            }else{
                id object = [self valueForKey:key];
                if (object&&![object isKindOfClass:[NSNull class]]) {
                    //写入到存储里，这里说明有值，但是没存储的
                    [self writeIntoDefWithObject:object forKey:key];
                }
            }
            
            self.disableSynchronize = NO;
            
            //对应添加KVO
            [self addObserver:self forKeyPath:key options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
        }
        
        
        [self doAfterSetValuesFromUserDefault];
    }
    return self;
}

- (void)dealloc
{
    //获取属性
    NSDictionary *propToTypes = [[MLClassPropManager manager]propToTypesOfClass:[self class] untilSuperClass:[MLUserDefault class] ignoreUntilClass:YES];
    
    NSArray *ignoreKeys = [self ignoreKeys];
    for (NSString *key in [propToTypes allKeys]) {
        if ([ignoreKeys containsObject:key]) {
            continue;
        }
        
        //对应删除KVO
        [self removeObserver:self forKeyPath:key context:nil];
    }
}


#pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    NSNumber *kind = [change objectForKey:NSKeyValueChangeKindKey];
    
    if ([kind integerValue] == NSKeyValueChangeSetting) {
        id newObject = [change objectForKey:NSKeyValueChangeNewKey];
        //写入userdefault
        [self writeIntoDefWithObject:newObject forKey:keyPath];
    }else{
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
    
}

#pragma mark - synchronize
- (void)setDisableSynchronize:(BOOL)disableSynchronize
{
    _disableSynchronize = disableSynchronize;
    if (!disableSynchronize) {
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
}

#pragma mark - helper
- (void)writeIntoDefWithObject:(id)newObject forKey:(NSString*)keyPath
{
    NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
    NSString *key = [NSString stringWithFormat:@"%@%@",kPrefixKeyOfUserDefault,keyPath];
    if (!newObject||[newObject isKindOfClass:[NSNull class]]) {
        [def removeObjectForKey:key];
    }else{
        if ([newObject isKindOfClass:[ModelArray class]]) {
            [def setObject:[newObject convertedArrayWithIgnoreNil:YES] forKey:key];
        }else if ([newObject isKindOfClass:[Model class]]){
            [def setObject:[newObject convertedDictionaryWithIgnoreNil:YES] forKey:key];
        }else if([newObject isKindOfClass:[NSURL class]]) {
            [def setObject:[newObject absoluteString] forKey:key];
        }else{
            [def setObject:newObject forKey:key];
        }
    }
    
    if (!self.disableSynchronize) {
        [def synchronize];
    }
}

@end
